use std::cell::RefCell;
use std::fmt::{Debug};
use std::rc::Rc;
use yew::{html, Component, Context, Html, Properties};
use crate::business::component::im_trait::{Id, Render};

pub struct ListView<T: Render + 'static + Id>  {
    data: Rc<RefCell<Vec<T>>>,
    select_node_id: Option<T::Value>,
}

#[derive(Properties, Clone, PartialEq, Debug)]
#[derive(Default)]
pub struct ListProps {
    #[prop_or(1000)]
    pub(crate) max_size: u16,
    #[prop_or_default]
    pub class: String,
}

pub enum ListMsg<T: Render + 'static> {
    AddLastData(T),
    AddLastDataList(Vec<T>),
    AddFirstData(T),
    AddFirstDataList(Vec<T>),
    UpdateData(T),
    UpdateDataList(Vec<T>),
    RemoveData(T),
    RemoveDataList(Vec<T>),
    Clean,
    Set(Vec<T>),
}

impl <T: Render + 'static + Id> Component for ListView<T> {
    type Message = ListMsg<T>;
    type Properties = ListProps;

    fn create(_ctx: &Context<Self>) -> Self {
        Self { data: Rc::new(RefCell::new(Vec::new())), select_node_id: None }
    }

    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            ListMsg::AddLastData(data) => {
                let data_list = self.data.clone();
                self.select_node_id = Some(data.id());
                data_list.borrow_mut().push(data);

                self.remove_old_data(ctx, 1);
                true
            }
            ListMsg::AddLastDataList(list) => {
                let data_list = self.data.clone();
                let new_data_len = list.len();
                if new_data_len > 0 {
                    let id = (&list[new_data_len-1]).id();
                    log::info!("add last datas: {}", id);
                    self.select_node_id = Some(id);
                }
                data_list.borrow_mut().extend(list);

                self.remove_old_data(ctx, new_data_len);
                true
            }
            ListMsg::AddFirstData(data) => {
                let data_list = self.data.clone();
                self.select_node_id = Some(data.id());
                data_list.borrow_mut().insert(0, data);

                self.remove_new_data(ctx, 1);
                true
            }
            ListMsg::AddFirstDataList(list) => {
                let data_list = self.data.clone();
                let new_data_len = list.len();
                if new_data_len > 0 {
                    self.select_node_id = Some(list[0].id());
                }
                data_list.borrow_mut().splice(0..0, list.into_iter());
                self.remove_new_data(ctx, new_data_len);
                true
            }
            ListMsg::UpdateData(mut data) => {
                let data_list = self.data.clone();
                let position = data_list.borrow().iter().position(|value| data.id() == value.id());
                if let Some(position) = position {
                    let mut tt = data_list.borrow_mut();
                    let old_data = tt.get_mut(position).unwrap();
                    std::mem::swap(&mut data, old_data);

                    self.select_node_id = Some(data.id());
                    return true;
                }
                false
            }
            ListMsg::UpdateDataList(mut datas) => {
                let data_list = self.data.clone();
                for mut data in datas.into_iter() {
                    let position = data_list.borrow().iter().position(|value| data.id() == value.id());
                    if let Some(position) = position {
                        let mut tt = data_list.borrow_mut();
                        let old_data = tt.get_mut(position).unwrap();
                        std::mem::swap(&mut data, old_data);

                        self.select_node_id = Some(data.id());
                        return true;
                    }
                }
                false
            }
            ListMsg::RemoveData(mut data) => {
                let data_list = self.data.clone();
                let position = data_list.borrow().iter().position(|value| data.id() == value.id());
                if let Some(p) = position {
                    if let Some(_select_node_id) = &self.select_node_id {
                        let tt = data_list.borrow();
                        if p < data_list.borrow().len() + 1 {
                            self.select_node_id = Some(tt.get(p+1).unwrap().id())
                        } else {
                            self.select_node_id = Some(tt.get(p-1).unwrap().id())
                        }
                    }
                    data_list.borrow_mut().remove(p);
                }
                true
            }
            ListMsg::RemoveDataList(list) => {
                let data_list = self.data.clone();
                list.into_iter().for_each(|data|{
                    let position = data_list.borrow().iter().position(|value| data.id() == value.id());
                    if let Some(p) = position {
                        data_list.borrow_mut().remove(p);
                    }
                });
                true
            }
            ListMsg::Clean => {
                let data_list = self.data.clone();
                data_list.borrow_mut().clear();
                self.select_node_id = None;
                true
            }
            ListMsg::Set(data) => {
                let lasted = data.last();
                if let Some(lasted) = lasted {
                    self.select_node_id = Some(lasted.id());
                }

                let data_list = self.data.clone();
                data_list.borrow_mut().clear();
                data_list.borrow_mut().extend(data);

                true
            }
        }
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let ListProps { class, .. } = ctx.props().clone();
        html!{
            <div class="list-view minimal">
                { self.data.borrow().iter().map(|data|{data.render()}).collect::<Vec<Html>>() }
            </div>
        }
    }

    fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) {
        let select_node_id = self.select_node_id.clone();
        log::info!("select node id, {}, {}", select_node_id.is_some(), first_render);
        if !first_render {
            if let Some(node_id) = select_node_id {
                // let last_node_id = self.data.borrow().last().map(|data| { format!("item_{}", data.id()) }).unwrap_or("item_0".to_string());
                let show_node_id = format!("item_{}", node_id);
                log::info!("select node id2, {}", show_node_id);
                scroll_to_node(show_node_id);
            }
        }
    }
}

impl <T: Render + 'static + Id> ListView<T> {

    pub fn remove_new_data(&mut self, ctx: &Context<Self>, size: usize) {
        let data_list = self.data.clone();
        let mut data_list_mut = data_list.borrow_mut();
        let len = data_list_mut.len();
        if len > ctx.props().max_size as usize && size > 0 {
            if len > size {
                data_list_mut.truncate(len - size);
            } else {
                data_list_mut.clear();
            }
        }
    }

    pub fn remove_old_data(&mut self, ctx: &Context<Self>, size: usize) {
        let data_list = self.data.clone();
        let mut data_list_mut = data_list.borrow_mut();
        let len = data_list_mut.len();
        if len > ctx.props().max_size as usize && size > 0 {
            log::info!("remove old data, {}, {}, {}", len, ctx.props().max_size, size);
            if len > size {
                data_list_mut.drain(0..size);
            }
        }
    }
}

impl ListProps {
    pub fn new(max_size: u16) -> Self {
        Self {
            max_size,
            class: "".to_string(),
        }
    }
}

pub fn scroll_to_node(node_id: String) {
    if let Some(window) = web_sys::window() {
        if let Some(document) = window.document() {
            // 查找所有关闭按钮并触发点击
            if let Some(element) = document.get_element_by_id(&node_id) {
                element.scroll_into_view();
            }
        }
    }
}